IVS Low-Latency StreamingのPlayback Restriction PolicyでStrict Origin Enforcement有効時の挙動を確認してみた
はじめに
清水です。先日2024/02/01のアップデートで、Amazon Interactive Video Service (Amazon IVS)のLow-Latency Streamingでポリシーによる再生制限ができるPlayback restriction policiesが利用可能になりました。
本DevelopersIOでも以下エントリで速報としてお届けしています。
上記のエントリではPlayback Restriction Policyの2つの機能、geo-blockingとcross-origin resource sharing (CORS)レスポンスヘッダそれぞれで、設定の際の基本的な挙動について確認しています。ただし、 Strict Origin Enforcemnet というオプションについては動作を省略していました。このStrict Origin Enforcement、デフォルトの無効状態ではOriginヘッダによる制限がトップレベルのマニフェスファイル(IVSの用語ではMultivariant playlist)のみに適用されます。Strict Origin Enforcementを有効にすることで、Multivariant playliset以外のすべてのリクエストに対しても、Originヘッダによる制限を適用するという機能のようです。
Note on strict origin enforcement: This is an optional setting that can be used to strengthen the origin restriction specified with allowed origins. By default, the origin restriction applies only to the multivariant playlist. If strict origin enforcement is enabled, the server will enforce a requirement that the requesting origin matches the token for all playback requests (including multivariant playlist, variant playlist, and segments). This means that all clients (including non-browser clients) will have to provide a valid origin-request header with each request. Use the setOrigin method to set the header in the IVS iOS and Android player SDKs. It is set automatically in web browsers except iOS Safari. For iOS Safari, you need to add crossorigin="anonymous" to the video element, to ensure that the origin request header is sent. Example: <video crossorigin="anonymous"></video>.
Console Instructions (Playback Restriction Policy) - Amazon Interactive Video Service
本エントリでは、このStrict Origin Enforcementを有効に設定して、Playback Restriction PolicyのAllowed Originで指定したOriginヘッダを用いてアクセスした場合、または指定したOriginヘッダを用いずにアクセスした場合の挙動を確認してみましたのでまとめてみます。なかなかの長文エントリとなってしまいました。左側のインデックスを活用していただきつつ、まずは結果が確認したい、という場合は「検証結果のまとめ」から確認いただくとよいかと思います。
なお本ブログエントリの内容、具体的にはレスポンスヘッダの詳細やレスポンスのステータスコードなどといった細かな挙動について、User Guideに記載されていない項目は変更される可能性がないとは言い切れません。あくまでUser Guide記載の挙動を基準に処理などを行いましょう。また、今回の動作検証ではCORSのプリフライトリクエストについては考慮していません。
動作確認環境や確認内容について
動作確認を行った検証環境についてあらかじめまとめておきます。
リソースは以下環境のAWS CLIで作成、操作しました。
% aws --version aws-cli/2.15.17 Python/3.11.6 Darwin/22.6.0 exe/x86_64 prompt/off
AWS CLIでのIVS Playback restriction policiesの操作については以下ブログエントリを参照ください。
上記エントリを執筆した先日2024/02/02の段階ではAWS CLI v2ではPlayback restriction policiesに対応していませんでしたが、2.15.17からサポートしたようです。
IVS Low-Latency Streaming Channelの作成とストリーミング実施
Channelは以下で作成しました。デフォルト設定でaws ivs create-channel
を実行しています。
% aws ivs create-channel \ --name "strict-origin-enforcement-test-channel" { "channel": { "arn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "authorized": false, "ingestEndpoint": "62xxxxxxxx2b.global-contribute.live-video.net", "insecureIngest": false, "latencyMode": "LOW", "name": "strict-origin-enforcement-test-channel", "playbackRestrictionPolicyArn": "", "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8", "preset": "", "recordingConfigurationArn": "", "tags": {}, "type": "STANDARD" }, "streamKey": { "arn": "arn:aws:ivs:ap-northeast-1:123456789012:stream-key/LAxxxxxxxx23", "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "tags": {}, "value": "sk_ap-northeast-1_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } }
Channel作成後、AWSマネジメントコンソールからストリーミングを行っています。操作方法などについては以下を参照ください。
マネジメントコンソールからストリーミングを行い、aws ivs get-stream
コマンドで配信中の状態であること、ならびにPlayback URLを確認しておきます。
% aws ivs get-stream \ --channel-arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd" { "stream": { "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "health": "HEALTHY", "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8", "startTime": "2024-02-08T06:33:01+00:00", "state": "LIVE", "streamId": "st-1HxxxxxxxxxxxxxxxxxxxyT", "viewerCount": 0 } }
リクエスト対象の各ファイルについて
続いて、動作を確認した(実際にリクエストを行った)ファイルについて確認しておきましょう。
まずはPlayback URLで得られる以下URLです。HLSの再生に必要なマニフェストファイルの中でも、最上位(起点)となるトップレベルのマニフェスファイルですね。Amazon IVS Low-Latency Streamingの用語(Glossary - Amazon Interactive Video Service)としては Multivariant playlist と呼んでいますので、本ブログエントリでも以降はこの呼称とします。
- https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8
このMultivariant playlistの中身は、以下のように複数のマニフェストファイルで構成されています。Rendition(Adaptive Bitrate (ABR) Streamingの解像度やビットレートの組み合わせ)ごとに異なるプレイリストとなっているぐあいですね。子プレイリストなどとも呼ばれますが、ここでもIVSのUser Guideにならい 本エントリでは variant playlist と称することとします。なお、Renditionの数はIVSのChannel Typeや入力動画の解像度等によって異なります。
#EXTM3U #EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-65acdc.tyo03" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03" #EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707375471.67" #EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1" #EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]" #EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="1495.671007" #EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05" #EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012" #EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列1]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列2]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列3]).m3u8
このファイル内、複数のRenditionの中で一番上位のプレイリストファイル、ここではNAME="480p"
のものにアクセスします。
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列1]).m3u8
variant playlistにアクセスすると、数秒ごとに区切られた動画ファイルで構成されたプレイリストが得られます。セグメントファイルと呼ばれるものですね。こちらもIVS User Guideにならい、 segments と本エントリ内では表記します。
#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:771 #EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:771 #EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:1542.002 #EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:1574.053 #EXT-X-DATERANGE:ID="playlist-creation-1707375550",CLASS="timestamp",START-DATE="2024-02-07T22:59:10.452-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707375550.45" #EXT-X-DATERANGE:ID="source-1707375520",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T06:58:40.089Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live" #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:40.089Z #EXTINF:2.012,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列1].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:42.101Z #EXTINF:2.017,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列2].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:44.118Z #EXTINF:1.978,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列3].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:46.096Z #EXTINF:2.012,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列4].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:48.108Z #EXTINF:2.014,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列5].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:50.122Z #EXTINF:1.980,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列6].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:52.102Z #EXTINF:2.013,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列7].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:54.115Z #EXTINF:1.980,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列8].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:56.095Z #EXTINF:2.013,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列9].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:58.108Z #EXTINF:1.980,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列10].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:00.088Z #EXTINF:2.011,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列11].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:02.099Z #EXTINF:2.015,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列12].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:04.114Z #EXTINF:1.978,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列13].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:06.092Z #EXTINF:2.016,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列14].ts #EXT-X-PREFETCH:https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列15].ts #EXT-X-PREFETCH:https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列16].ts
最下部にはLL-HLS (Low-Latency HLS)用の#EXT-X-PREFETCH
に続きsegmentsへのURLが並びますが、今回はその#EXT-X-PREFETCH
タグの1つ上にあるsegmentsへアクセスすることとします。
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:06.092Z #EXTINF:2.016,live https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列14].ts
以上で、アクセス対象となる multivariant playlist 、 variant playlist 、そして segments について、どのファイルであるかの確認ができました。
Playback Restriction Policyを適用していない状態でのレスポンスヘッダの確認
確認の対象となるストリーミング再生のためのファイルについて確認できたところで、まずはPlayback Restriction Policyを適用していない状態でのレスポンスヘッダについて確認してみましょう。以下3パターンで確認していきたいと思います。
まず1つ目のパターンでは、リクエスト時に "https://allowed-origin.example.net" という値のOriginヘッダを付与します。このOriginヘッダの値は動画プレイヤーを埋め込んだWebサイトの想定です。意図したOriginヘッダの値であるため、レスポンスではCORS用の適切なAccess-Control-Allow-Originヘッダが含まれることが期待されます。このパターンは 許可想定のOriginヘッダ値を付与したリクエスト と表記することとします。
以下がリクエスト実行のフォーマットです。curlコマンドを用いて実行します。
curl -i -H "Origin: https://allowed-origin.example.net" <アクセス対象の各ファイル>
なおcurlコマンドに-i
オプションを付与してレスポンスボディに加えてレスポンスヘッダを表示させています。-I
オプションでレスポンスヘッダのみを表示させることも考えたのですが、GETリクエストとHEADリクエストの違いないのか、-I
オプションでは一部ファイルで付与されるレスポンスヘッダ内でtransfer-encoding: chunked
がなくなっていたため、本エントリ内では-i
オプションを使用することとしました。
2つ目パターンでは、リクエスト時に "https://not-allowed-origin.example.net" という値のOriginヘッダを付与します。このOriginヘッダは動画プレイヤーを埋め込んだ正しいWebサイト ではない ホスト名という想定です。Playback Restriction Policyを使用することで、レスポンスに適切なAccess-Control-Allow-Originヘッダを含まずに再生を制限することが期待されます。 許可をしていない想定のOriginヘッダ値を付与したリクエスト と表記します。
curl -i -H "Origin: https://not-allowed-origin.example.net" <アクセス対象の各ファイル>
3つ目のパターンは、リクエスト時にOriginヘッダを指定しないものです。こちらもPlayback Restriction Policyを使用することで、レスポンスに適切なAccess-Control-Allow-Originヘッダを含まずに再生を制限することが期待されます。 Originヘッダなしのリクエスト と称します。
curl -i <アクセス対象の各ファイル>
確認する3つのパターンを抑えたところで、実際にまずは、Playback Restriction Policyを適用していない状態でのレスポンスヘッダを確認してみます。
許可想定のOriginヘッダ値を付与したリクエスト
まずは許可想定のOriginヘッダ値を付与したリクエストです。multivariant playlist、variant playlist、segmentsのいずれでも、レスポンスヘッダにaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)が付与されていることがわかります。Playback Restriction Policyを適用していない状態ではOriginヘッダの値によるストリーミングの再生制限は行われません。許可を想定したOriginヘッダ値を付与してリクエストしても、すべてのWebサイト(ドメイン)に対して再生が許可される値が*
の値でaccess-control-allow-originヘッダがレスポンスとして返されます。
multivariant playlist
% curl -i -H "Origin: https://allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 6123 vary: Accept-Encoding date: Thu, 08 Feb 2024 07:26:33 GMT access-control-allow-origin: * x-amzn-trace-id: Root=1-65xxxx29-57xxxxxxxxxxxxxxxxxxxxc3 x-amzn-trace-id: Root=1-65xxxx29-57xxxxxxxxxxxxxxxxxxxxc3 x-cache: Miss from cloudfront via: 1.1 09xxxxxxxxxxxxxxxxxxxxxxxxxxxxf6.cloudfront.net (CloudFront) x-amz-cf-pop: HKG54-C1 x-amz-cf-id: 03xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== #EXTM3U #EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-b02154.tyo03" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03" #EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707377193.14" #EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1" #EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]" #EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="3217.135438" #EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05" #EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012" #EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列4]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列5]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列6]).m3u8
variant playlist
% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列4]).m3u8" HTTP/1.1 200 OK cache-control: no-cache, no-store, private content-type: application/vnd.apple.mpegurl vary: Accept-Encoding date: Thu, 08 Feb 2024 07:27:57 GMT transfer-encoding: chunked access-control-allow-origin: * #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:1634 #EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:1634 #EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:3267.999 #EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:3301.959 #EXT-X-DATERANGE:ID="playlist-creation-1707377277",CLASS="timestamp",START-DATE="2024-02-07T23:27:57.887-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707377277.89" #EXT-X-DATERANGE:ID="source-1707377246",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:27:26.086Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live" #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:26.086Z #EXTINF:2.021,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列17].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:28.107Z #EXTINF:2.006,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列18].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:30.113Z #EXTINF:1.986,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列19].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:32.099Z #EXTINF:2.009,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列20].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:34.108Z #EXTINF:1.979,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列21].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:36.087Z #EXTINF:2.016,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列22].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:38.103Z #EXTINF:1.978,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列23].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:40.081Z #EXTINF:2.017,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列24].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:42.098Z #EXTINF:2.011,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列25].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:44.109Z #EXTINF:1.980,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列26].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:46.089Z #EXTINF:2.010,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列27].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:48.099Z #EXTINF:1.984,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列28].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:50.083Z #EXTINF:2.013,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列29].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:52.096Z #EXTINF:2.010,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列30].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:54.106Z #EXTINF:1.980,live https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列31].ts #EXT-X-PREFETCH:https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列32].ts #EXT-X-PREFETCH:https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列33].ts
segments
% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列31].ts" HTTP/1.1 200 OK Accept-Ranges: bytes Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Type: application/octet-stream Date: Thu, 08 Feb 2024 07:29:16 GMT Transfer-Encoding: chunked Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
許可をしていない想定のOriginヘッダ値を付与したリクエスト
続いて許可をしていない想定のOriginヘッダ値を付与したリクエストです。繰り返しになりますが、Playback Restriction Policyを適用していない状態ではOriginヘッダによる制限は行われません。このパターンでもmultivariant playlist、variant playlist、segmentsそれぞれでヘッダにaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)が付与されたレスポンスが返り、いずれのWebサイトでもストリーミング再生が可能となります。
multivariant playlist
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 6123 vary: Accept-Encoding date: Thu, 08 Feb 2024 07:32:08 GMT access-control-allow-origin: * x-amzn-trace-id: Root=1-65xxxx78-3fxxxxxxxxxxxxxxxxxxxx2f x-amzn-trace-id: Root=1-65xxxx78-3fxxxxxxxxxxxxxxxxxxxx2f x-cache: Miss from cloudfront via: 1.1 d5xxxxxxxxxxxxxxxxxxxxxxxxxxxx4e.cloudfront.net (CloudFront) x-amz-cf-pop: KIX50-P1 x-amz-cf-id: cjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== #EXTM3U #EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-ab9cf4.tyo03" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03" #EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707377528.08" #EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1" #EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]" #EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="3552.077476" #EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05" #EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012" #EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列7]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列8]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列9]).m3u8%
variant playlist
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列7]).m3u8" HTTP/1.1 200 OK cache-control: no-cache, no-store, private content-type: application/vnd.apple.mpegurl vary: Accept-Encoding date: Thu, 08 Feb 2024 07:34:05 GMT transfer-encoding: chunked access-control-allow-origin: * #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:1819 #EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:1819 #EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:3637.999 #EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:3670.039 #EXT-X-DATERANGE:ID="playlist-creation-1707377645",CLASS="timestamp",START-DATE="2024-02-07T23:34:05.165-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707377645.16" #EXT-X-DATERANGE:ID="source-1707377616",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:33:36.086Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live" #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:36.086Z #EXTINF:2.011,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列34].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:38.097Z #EXTINF:2.013,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列35].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:40.110Z #EXTINF:1.983,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列36].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:42.093Z #EXTINF:2.016,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列37].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:44.109Z #EXTINF:2.007,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列38].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:46.116Z #EXTINF:2.016,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列39].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:48.132Z #EXTINF:1.978,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列40].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:50.110Z #EXTINF:1.978,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列41].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:52.088Z #EXTINF:2.013,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列42].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:54.101Z #EXTINF:1.985,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列43].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:56.086Z #EXTINF:2.012,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列44].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:58.098Z #EXTINF:1.984,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列45].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:34:00.082Z #EXTINF:2.008,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列46].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:34:02.090Z #EXTINF:2.012,live https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列47].ts #EXT-X-PREFETCH:https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列48].ts #EXT-X-PREFETCH:https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列49].ts
segments
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列47].ts" HTTP/1.1 200 OK Accept-Ranges: bytes Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Type: application/octet-stream Date: Thu, 08 Feb 2024 07:34:48 GMT Transfer-Encoding: chunked Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
Originヘッダなしのリクエスト
続いてはOriginヘッダがない場合のリクエストについての確認です。こちらもPlayback Restriction Policyを適用していない状態では、いずれのファイルへのリクエストでもそれぞれレスポンスヘッダにaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)が付与されていました。Originヘッダがない場合にはAccess-Control-Allow-Originヘッダを返さない、という環境もあるかと思いますが(例えばAmazon S3はこのような動作だった認識です)、IVSでPlayback Restriction Policyを適用していない場合は、リクエスト時にOriginヘッダがなくともレスポンスとしてaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)が返ってくる、という動作になります。
multivariant playlist
% curl -i "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 6126 vary: Accept-Encoding date: Thu, 08 Feb 2024 07:37:19 GMT access-control-allow-origin: * x-amzn-trace-id: Root=1-65xxxxaf-3axxxxxxxxxxxxxxxxxxxxf6 x-amzn-trace-id: Root=1-65xxxxaf-3axxxxxxxxxxxxxxxxxxxxf6 x-cache: Miss from cloudfront via: 1.1 cexxxxxxxxxxxxxxxxxxxxxxxxxxxx40.cloudfront.net (CloudFront) x-amz-cf-pop: KIX50-P1 x-amz-cf-id: -sxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== #EXTM3U #EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-b01e58.tyo03" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03" #EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707377839.86" #EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1" #EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]" #EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="3863.862990" #EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05" #EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012" #EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列10]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列11]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列12]).m3u8%
variant playlist
% curl -i "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列10]).m3u8" HTTP/1.1 200 OK cache-control: no-cache, no-store, private content-type: application/vnd.apple.mpegurl vary: Accept-Encoding date: Thu, 08 Feb 2024 07:37:50 GMT transfer-encoding: chunked access-control-allow-origin: * #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:1931 #EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:1931 #EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:3862.004 #EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:3895.958 #EXT-X-DATERANGE:ID="playlist-creation-1707377870",CLASS="timestamp",START-DATE="2024-02-07T23:37:50.717-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707377870.72" #EXT-X-DATERANGE:ID="source-1707377840",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:37:20.091Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live" #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:20.091Z #EXTINF:2.010,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列50].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:22.101Z #EXTINF:1.981,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列51].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:24.082Z #EXTINF:2.020,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列52].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:26.102Z #EXTINF:2.007,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列53].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:28.109Z #EXTINF:1.985,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列54].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:30.094Z #EXTINF:2.007,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列55].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:32.101Z #EXTINF:1.980,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列56].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:34.081Z #EXTINF:2.016,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列57].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:36.097Z #EXTINF:1.979,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列58].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:38.076Z #EXTINF:2.012,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列59].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:40.088Z #EXTINF:2.014,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列60].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:42.102Z #EXTINF:1.985,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列61].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:44.087Z #EXTINF:2.044,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列62].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:46.131Z #EXTINF:1.974,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列63].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:48.105Z #EXTINF:1.980,live https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列64].ts #EXT-X-PREFETCH:https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列65].ts #EXT-X-PREFETCH:https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列66].ts
segments
% curl -i "https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列64].ts" HTTP/1.1 200 OK Accept-Ranges: bytes Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Type: application/octet-stream Date: Thu, 08 Feb 2024 07:38:25 GMT Transfer-Encoding: chunked Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
Playback Restriction Policyの作成と適用
Playback Restriction Policyを適用していない場合、リクエスト時のOriginヘッダの有無そしてその内容(値)にかかわらずレスポンスヘッダにはaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)が含まれており、Originヘッダによるストリーミング再生の制限制限は行われていないことが確認できました。
続いてPlayback Restriction Policyを適用した状態での確認に入りますが、その前にPlayback Restriction Policyの作成とChannelへの適用を行います。
Playback Restriction Policyの作成
Playback Restriction Policyの作成もAWS CLIで行います。以下のようにaws ivs create-playback-restriction-policy
コマンドで作成しました。ストリーミング再生を許可するサイトドメインとして https://allowed-origin.example.net を--allowed-origins
オプションで指定します。またStrict Origin Enforcmentについてはオプションで指定を行わず、デフォルトの無効状態で作成します。("enableStrictOriginEnforcement": false
)
% aws ivs create-playback-restriction-policy \ --name "strict-origin-enforcement-test-policy" \ --allowed-origins '["https://allowed-origin.example.net"]' { "playbackRestrictionPolicy": { "allowedCountries": [], "allowedOrigins": [ "https://allowed-origin.example.net" ], "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB", "enableStrictOriginEnforcement": false, "name": "strict-origin-enforcement-test-policy", "tags": {} } }
Playback Restriction PolicyのChannelへのアタッチ
続いて作成したPlayback Restriction PolicyをChannelリソースに関連付けます。Channelでライブストリーム中はアタッチできない(UpdateChannel
でエラーとなってしまう)ため、マネジメントコンソールからライブストリームを中断してaws ivs update-channel
コマンドを実行しました。
aws ivs update-channel
コマンド実行前、さきほどの「Playback Restriction Policyを適用していない状態でのレスポンスヘッダの確認」を行った状態ではPolicyは未設定でした。
% aws ivs get-channel \ --arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd" { "channel": { "arn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "authorized": false, "ingestEndpoint": "62xxxxxxxx2b.global-contribute.live-video.net", "insecureIngest": false, "latencyMode": "LOW", "name": "strict-origin-enforcement-test-channel", "playbackRestrictionPolicyArn": "", "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8", "preset": "", "recordingConfigurationArn": "", "tags": {}, "type": "STANDARD" } }
aws ivs update-channel
を実行します。"playbackRestrictionPolicyArn"
に値が含まれていることが確認できますね。
% aws ivs update-channel \ --arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd" \ --playback-restriction-policy-arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB" { "channel": { "arn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "authorized": false, "ingestEndpoint": "62xxxxxxxx2b.global-contribute.live-video.net", "insecureIngest": false, "latencyMode": "LOW", "name": "strict-origin-enforcement-test-channel", "playbackRestrictionPolicyArn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB", "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8", "preset": "", "recordingConfigurationArn": "", "tags": {}, "type": "STANDARD" } }
% aws ivs get-channel \ --arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd" { "channel": { "arn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "authorized": false, "ingestEndpoint": "62xxxxxxxx2b.global-contribute.live-video.net", "insecureIngest": false, "latencyMode": "LOW", "name": "strict-origin-enforcement-test-channel", "playbackRestrictionPolicyArn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB", "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8", "preset": "", "recordingConfigurationArn": "", "tags": {}, "type": "STANDARD" } }
Playback Restriction PolicyをChannelにアタッチ後、再度AWSマネジメントコンソールからストリームを行います。aws ivs get-stream
コマンドでライブストリーミング中であることを確認しておきましょう。
% aws ivs get-stream \ --channel-arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd" { "stream": { "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "health": "HEALTHY", "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8", "startTime": "2024-02-08T07:46:11+00:00", "state": "LIVE", "streamId": "st-1CxxxxxxxxxxxxxxxxxxxpY", "viewerCount": 0 } }
Playback Restriction PolicyでAllowed Originを追加した状態でのレスポンスヘッダの確認
Playback Restriction PolicyをアタッチしたChannelの準備ができ、ライブストリーミングを再開しました。この状態、Playback Restriction PolicyでAllowed Originを追加した状況下でレスポンスヘッダの確認をしてみましょう。
ChannelにアタッチしているPlayback Restriction Policyでは"allowedOrigins"
として許可対象の "https://allowed-origin.example.net" を追加、Strict Origin Enforcmentは無効の状態です。
% aws ivs get-playback-restriction-policy \ --arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB" { "playbackRestrictionPolicy": { "allowedCountries": [], "allowedOrigins": [ "https://allowed-origin.example.net" ], "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB", "enableStrictOriginEnforcement": false, "name": "strict-origin-enforcement-test-policy", "tags": {} } }
許可想定のOriginヘッダ値を付与したリクエスト
まずは許可想定のOriginヘッダ値を付与したリクエストです。multivariant playlistではレスポンスヘッダとして、許可想定としたホスト名である https://allowed-origin.example.net を値にしたaccess-control-allow-originヘッダ、 access-control-allow-origin: https://allowed-origin.example.net が含まれていました。
variant playlistならびにsegmentsでは、access-control-allow-origin: *
(Access-Control-Allow-Origin: *
)とaccess-control-allow-originヘッダの値はワイルドカード *
で、どのホスト名でもCORSを許可する状態です。最上位のmultivariant playlistでのみ、ホスト名(埋め込みWebサイトのドメイン)を制限している状況ですね。
multivariant playlist
% curl -i -H "Origin: https://allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 6125 vary: Accept-Encoding date: Thu, 08 Feb 2024 07:48:08 GMT access-control-allow-origin: https://allowed-origin.example.net x-amzn-trace-id: Root=1-65xxxx38-6cxxxxxxxxxxxxxxxxxxxxdd x-amzn-trace-id: Root=1-65xxxx38-6cxxxxxxxxxxxxxxxxxxxxdd x-cache: Miss from cloudfront via: 1.1 22xxxxxxxxxxxxxxxxxxxxxxxxxxxx46.cloudfront.net (CloudFront) x-amz-cf-pop: KIX50-P1 x-amz-cf-id: DJxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== #EXTM3U #EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-785cca.tyo03" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03" #EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707378488.38" #EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1" #EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]" #EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="122.377198" #EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05" #EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012" #EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列13]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列14]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列15]).m3u8%
variant playlist
% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列13]).m3u8" HTTP/1.1 200 OK cache-control: no-cache, no-store, private content-type: application/vnd.apple.mpegurl vary: Accept-Encoding date: Thu, 08 Feb 2024 07:49:11 GMT transfer-encoding: chunked access-control-allow-origin: * #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:77 #EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:77 #EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:153.986 #EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:186.018 #EXT-X-DATERANGE:ID="playlist-creation-1707378551",CLASS="timestamp",START-DATE="2024-02-07T23:49:11.912-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707378551.91" #EXT-X-DATERANGE:ID="source-1707378522",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:48:42.623Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live" #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:42.623Z #EXTINF:2.010,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列67].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:44.633Z #EXTINF:1.980,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列68].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:46.613Z #EXTINF:2.012,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列69].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:48.625Z #EXTINF:2.016,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列70].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:50.641Z #EXTINF:1.982,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列71].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:52.623Z #EXTINF:2.011,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列72].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:54.634Z #EXTINF:1.981,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列73].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:56.615Z #EXTINF:2.010,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列74].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:58.625Z #EXTINF:2.017,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列75].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:00.642Z #EXTINF:1.979,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列76].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:02.621Z #EXTINF:2.012,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列77].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:04.633Z #EXTINF:1.977,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列78].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:06.610Z #EXTINF:2.018,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列79].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:08.628Z #EXTINF:2.009,live https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列80].ts #EXT-X-PREFETCH:https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列81].ts #EXT-X-PREFETCH:https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列82].ts
segments
% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列80].ts" HTTP/1.1 200 OK Accept-Ranges: bytes Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Type: application/octet-stream Date: Thu, 08 Feb 2024 07:50:12 GMT Transfer-Encoding: chunked Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
許可をしていない想定のOriginヘッダ値を付与したリクエスト
続いて、許可をしていない想定のOriginヘッダ値を付与したリクエスト行ってみます。multivariant playlistではレスポンスに access-control-allow-origin ヘッダは含まれておらず、CORSエラーとなり動画再生が制限される状態となります。
ただし、variant playlistならびにsegmentsではaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)となっています。access-control-allow-originヘッダの値はワイルドカード *
で、どのホスト名でもCORSを許可する状態ですね。最上位のmultivariant playlistでのみ再生制限を行っていることが確認できます。
multivariant playlist
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 6125 vary: Accept-Encoding date: Thu, 08 Feb 2024 07:50:59 GMT x-amzn-trace-id: Root=1-65xxxxe3-58xxxxxxxxxxxxxxxxxxxxf5 x-amzn-trace-id: Root=1-65xxxxe3-58xxxxxxxxxxxxxxxxxxxxf5 x-cache: Miss from cloudfront via: 1.1 4bxxxxxxxxxxxxxxxxxxxxxxxxxxxxe4.cloudfront.net (CloudFront) x-amz-cf-pop: KIX50-P1 x-amz-cf-id: Y5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== #EXTM3U #EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-0465f4.tyo03" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03" #EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707378659.60" #EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1" #EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]" #EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="293.600672" #EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05" #EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012" #EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列16]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列17]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列18]).m3u8%
variant playlist
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列16]).m3u8" HTTP/1.1 200 OK cache-control: no-cache, no-store, private content-type: application/vnd.apple.mpegurl vary: Accept-Encoding date: Thu, 08 Feb 2024 07:52:14 GMT transfer-encoding: chunked access-control-allow-origin: * #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:168 #EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:168 #EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:335.981 #EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:368.029 #EXT-X-DATERANGE:ID="playlist-creation-1707378734",CLASS="timestamp",START-DATE="2024-02-07T23:52:14.364-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707378734.36" #EXT-X-DATERANGE:ID="source-1707378704",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:51:44.618Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live" #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:44.618Z #EXTINF:2.013,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列83].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:46.631Z #EXTINF:1.978,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列84].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:48.609Z #EXTINF:2.019,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列85].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:50.628Z #EXTINF:2.006,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列86].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:52.634Z #EXTINF:1.983,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列87].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:54.617Z #EXTINF:2.012,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列88].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:56.629Z #EXTINF:1.981,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列89].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:58.610Z #EXTINF:2.010,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列90].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:00.620Z #EXTINF:2.016,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列91].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:02.636Z #EXTINF:1.981,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列92].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:04.617Z #EXTINF:2.010,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列93].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:06.627Z #EXTINF:1.983,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列94].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:08.610Z #EXTINF:2.011,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列95].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:10.621Z #EXTINF:2.015,live https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列96].ts #EXT-X-PREFETCH:https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列97].ts #EXT-X-PREFETCH:https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列98].ts
segments
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列96].ts" HTTP/1.1 200 OK Accept-Ranges: bytes Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Type: application/octet-stream Date: Thu, 08 Feb 2024 07:52:51 GMT Transfer-Encoding: chunked Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
Originヘッダなしのリクエスト
Originヘッダなしでのリクエストも確認してみます。許可をしていない想定のOriginヘッダ値を付与したリクエストの場合と同様、multivariant playlistではレスポンスにaccess-control-allow-originヘッダを含まないこと、またvariant playlistならびにsegmentsではaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)となっていることが確認できます。
multivariant playlist
% curl -i "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 6125 vary: Accept-Encoding date: Thu, 08 Feb 2024 07:53:26 GMT x-amzn-trace-id: Root=1-65xxxx76-16xxxxxxxxxxxxxxxxxxxx57 x-amzn-trace-id: Root=1-65xxxx76-16xxxxxxxxxxxxxxxxxxxx57 x-cache: Miss from cloudfront via: 1.1 52xxxxxxxxxxxxxxxxxxxxxxxxxxxxe6.cloudfront.net (CloudFront) x-amz-cf-pop: HKG54-C1 x-amz-cf-id: JKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== #EXTM3U #EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-0465ec.tyo03" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03" #EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707378806.41" #EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1" #EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]" #EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="440.407106" #EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05" #EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012" #EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列19]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列20]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列21]).m3u8%
variant playlist
% curl -i "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列19]).m3u8" HTTP/1.1 200 OK cache-control: no-cache, no-store, private content-type: application/vnd.apple.mpegurl vary: Accept-Encoding date: Thu, 08 Feb 2024 07:53:55 GMT transfer-encoding: chunked access-control-allow-origin: * #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:219 #EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:219 #EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:437.982 #EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:470.032 #EXT-X-DATERANGE:ID="playlist-creation-1707378835",CLASS="timestamp",START-DATE="2024-02-07T23:53:55.196-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707378835.20" #EXT-X-DATERANGE:ID="source-1707378806",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:53:26.619Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live" #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:26.619Z #EXTINF:2.013,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列99].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:28.632Z #EXTINF:1.978,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列100].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:30.610Z #EXTINF:2.013,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列101].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:32.623Z #EXTINF:2.050,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列102].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:34.673Z #EXTINF:1.946,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列103].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:36.619Z #EXTINF:2.014,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列104].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:38.633Z #EXTINF:1.977,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列105].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:40.610Z #EXTINF:2.017,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列106].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:42.627Z #EXTINF:2.012,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列107].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:44.639Z #EXTINF:1.977,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列108].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:46.616Z #EXTINF:2.015,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列109].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:48.631Z #EXTINF:1.980,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列110].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:50.611Z #EXTINF:2.013,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列111].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:52.624Z #EXTINF:2.015,live https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列112].ts #EXT-X-PREFETCH:https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列113].ts #EXT-X-PREFETCH:https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列114].ts
segments
% curl -i "https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列112].ts" HTTP/1.1 200 OK Accept-Ranges: bytes Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Type: application/octet-stream Date: Thu, 08 Feb 2024 07:54:21 GMT Transfer-Encoding: chunked Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
Allowed Originに加えてStrict Origin Enforcementを有効にした状態でのレスポンスヘッダの確認
Playback Restriction Policyを適用していない状態のレスポンスヘッダ、そしてPlayback Restriction PolicyでAllowed Originを追加した(Strict Origin Enforcementを無効の)状態でのレスポンスヘッダを確認してきました。
さて、いよいよ本エントリの本題、Strict Origin Enforcementを有効にした状態でのレスポンスヘッダを確認していきましょう。
まずはPlayback Restriction Policyで無効だったStrict Origin Enforcementを有効にします。Playback Restriction PolicyのChannelへのアタッチ時はライブストリームの中断を伴いましたが、Playback Restriction Policyの変更自体はChannel側のライブストリーミングの中断は伴わずに実施できました。(Update ChannelかUpdate Policyかの違いですね。)
変更前の状態を確認しておきます。
% aws ivs get-stream \ --channel-arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd" { "stream": { "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "health": "HEALTHY", "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8", "startTime": "2024-02-08T07:46:11+00:00", "state": "LIVE", "streamId": "st-1CxxxxxxxxxxxxxxxxxxxpY", "viewerCount": 0 } }
% aws ivs get-playback-restriction-policy \ --arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB" { "playbackRestrictionPolicy": { "allowedCountries": [], "allowedOrigins": [ "https://allowed-origin.example.net" ], "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB", "enableStrictOriginEnforcement": false, "name": "strict-origin-enforcement-test-policy", "tags": {} } }
aws ivs update-playback-restriction-policy
コマンドを実行してStrict Origin Enforcementを有効にします。
% aws ivs update-playback-restriction-policy \ --arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB" \ --enable-strict-origin-enforcement { "playbackRestrictionPolicy": { "allowedCountries": [], "allowedOrigins": [ "https://allowed-origin.example.net" ], "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB", "enableStrictOriginEnforcement": true, "name": "strict-origin-enforcement-test-policy", "tags": {} } }
Allowed Originとして登録している内容(ホスト名)とStrict Origin Enfocementが有効になっていること、そしてライブストリーミング中であることを確認しておきましょう。
% aws ivs get-playback-restriction-policy \ --arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB" { "playbackRestrictionPolicy": { "allowedCountries": [], "allowedOrigins": [ "https://allowed-origin.example.net" ], "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB", "enableStrictOriginEnforcement": true, "name": "strict-origin-enforcement-test-policy", "tags": {} } }
% aws ivs get-stream \ --channel-arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd" { "stream": { "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd", "health": "HEALTHY", "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8", "startTime": "2024-02-08T07:46:11+00:00", "state": "LIVE", "streamId": "st-1CxxxxxxxxxxxxxxxxxxxpY", "viewerCount": 0 } }
許可想定のOriginヘッダ値を付与したリクエスト
まずは許可想定のOriginヘッダ値を付与したリクエストです。「Playback Restriction PolicyでAllowed Originを追加した状態でのレスポンスヘッダの確認」のとき、つまりStrict Origin Enforcementが無効だったときと同様の結果となりました。
multivariant playlistではレスポンスヘッダとして、許可想定としたホスト名である https://allowed-origin.example.net を値にした access-control-allow-originヘッダ、 access-control-allow-origin: https://allowed-origin.example.net が含まれています。
またvariant playlistならびにsegmentsでは、access-control-allow-origin: *
(Access-Control-Allow-Origin: *
)とaccess-control-allow-originヘッダの値はワイルドカード *
で、どのホスト名でもCORSを許可する状態です。
multivariant playlist
% curl -i -H "Origin: https://allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 6269 vary: Accept-Encoding date: Thu, 08 Feb 2024 07:59:06 GMT access-control-allow-origin: https://allowed-origin.example.net x-amzn-trace-id: Root=1-65xxxxca-4exxxxxxxxxxxxxxxxxxxx96 x-amzn-trace-id: Root=1-65xxxxca-4exxxxxxxxxxxxxxxxxxxx96 x-cache: Miss from cloudfront via: 1.1 e0xxxxxxxxxxxxxxxxxxxxxxxxxxxx7e.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: s0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== #EXTM3U #EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-785e36.tyo03" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03" #EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707379146.31" #EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1" #EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]" #EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]" #EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="780.311823" #EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true" #EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP" #EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03" #EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05" #EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]" #EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012" #EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd" #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列22]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列23]).m3u8 #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES #EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000 https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列24]).m3u8%
variant playlist
% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列22]).m3u8" HTTP/1.1 200 OK cache-control: no-cache, no-store, private content-type: application/vnd.apple.mpegurl vary: Accept-Encoding date: Thu, 08 Feb 2024 07:59:43 GMT transfer-encoding: chunked access-control-allow-origin: * #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:392 #EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:392 #EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:783.987 #EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:818.011 #EXT-X-DATERANGE:ID="playlist-creation-1707379183",CLASS="timestamp",START-DATE="2024-02-07T23:59:43.636-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707379183.64" #EXT-X-DATERANGE:ID="source-1707379152",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:59:12.624Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live" #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:12.624Z #EXTINF:2.014,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列115].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:14.638Z #EXTINF:1.978,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列116].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:16.616Z #EXTINF:2.016,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列117].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:18.632Z #EXTINF:1.979,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列118].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:20.611Z #EXTINF:2.013,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列119].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:22.624Z #EXTINF:2.014,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列120].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:24.638Z #EXTINF:1.980,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列121].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:26.618Z #EXTINF:2.013,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列122].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:28.631Z #EXTINF:1.976,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列123].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:30.607Z #EXTINF:2.013,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列124].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:32.620Z #EXTINF:2.051,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列125].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:34.671Z #EXTINF:1.946,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列126].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:36.617Z #EXTINF:2.011,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列127].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:38.628Z #EXTINF:1.981,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列128].ts #EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:40.609Z #EXTINF:2.013,live https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列129].ts #EXT-X-PREFETCH:https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列130].ts #EXT-X-PREFETCH:https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列131].ts
segments
% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列129].ts" HTTP/1.1 200 OK Accept-Ranges: bytes Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Type: application/octet-stream Date: Thu, 08 Feb 2024 08:00:16 GMT Transfer-Encoding: chunked Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.
許可をしていない想定のOriginヘッダ値を付与したリクエスト
続いて、許可をしていない想定のOriginヘッダ値を付与したリクエストを確認してみます。許可をしていない想定のホスト名である https://not-allowed-origin.example.net をOriginヘッダ値としてリクエストを行った場合、HTTPステータスコード403
が返りリクエストに失敗しました。Playlisetが取得できていない状況ですね。またエラーメッセージとしてplayback_auth_error
が返され、再生時の認証エラーであることが確認できます。Originヘッダの値をみて、正しいもの(ここではPlayback Restriction Policyに設定した https://allowed-origin.example.net )の場合にのみリクエストに応答する、という挙動になっているように見て取れます。なお、レスポンス自体にはaccess-control-allow-origin: *
がヘッダとして付与されています。
許可をしていない想定のOriginヘッダ値を付与したリクエストではmultivariant playlistが取得できないため、実際にはvariant playlistならびにsegmentsのURLもわからない、という状況になります。ですが今回は動作検証のため、許可想定のOriginヘッダ値 https://allowed-origin.example.net を付与してmultivariant playlisetを取得し直し、そのプレイリスト内のvariant playlistに対して許可をしていない想定のOriginヘッダ値でリクエストを行いました。variant playlisetのリクエストに対してもHTTPステータスコード403
が返り、こちらもリクエストに失敗してplaylistが取得できないという状況になりました。エラーメッセージとしてdisallowed origin
とも返されています。またレスポンス自体にはaccess-control-allow-origin: *
がヘッダとして付与されていました。
segmentsのURLの確認についてもvariant playlistのときと同様、許可想定のOriginヘッダ値 https://allowed-origin.example.net を付与してvariant playlistを取得し直して、そのプレイリスト内のsegmentsに対して許可をしていない想定のOriginヘッダ値でリクエストを行いましす。こちらもHTTPステータスコード403
と、disallowed origin
のメッセージがレスポンスされます。またAccess-Control-Allow-Origin: *
ヘッダもレスポンスに含まれていました。
multivariant playlist
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 403 content-type: application/json content-length: 159 date: Thu, 08 Feb 2024 08:01:17 GMT access-control-allow-origin: * x-amzn-trace-id: Root=1-65xxxx4d-49xxxxxxxxxxxxxxxxxxxx6b x-amzn-trace-id: Root=1-65xxxx4d-49xxxxxxxxxxxxxxxxxxxx6b x-cache: Error from cloudfront via: 1.1 06xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcc.cloudfront.net (CloudFront) x-amz-cf-pop: HKG54-C1 x-amz-cf-id: f9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== [{"url":"/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8","error":"playback_auth_error","error_code":"playback_auth_error","type":"error"}]%
variant playlist
いちどcurl -i -H "Origin: https://allowed-origin.example.net" <multivariant playlist>
で取得したプレイリスト内のvariant playlistを対象にリクエストを行います。
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列25]).m3u8" HTTP/1.1 403 Forbidden vary: Accept-Encoding x-error-message: disallowed origin date: Thu, 08 Feb 2024 08:02:21 GMT content-length: 0 access-control-allow-origin: *
segments
いちどcurl -i -H "Origin: https://allowed-origin.example.net" <variant playlist>
で取得したプレイリスト内のsegmentsに対してリクエストを行います。
% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-edge-4ff448.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列132].ts" HTTP/1.1 403 Forbidden Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Length: 17 disallowed origin
Originヘッダなしのリクエスト
Originヘッダなしでのリクエストについても確認します。基本的には「許可をしていない想定のOriginヘッダ値を付与したリクエスト」と同様の結果になりました。HTTPステータスコード403
が返り、multivariant playlist、variant playlist、そしてsegmentsのいずれも取得に失敗します。なおこの動作のため、variant playlistとsegmentsの取得には許可想定のOriginヘッダ値 https://allowed-origin.example.net を付与してリクエストをし直しています。「許可をしていない想定のOriginヘッダ値を付与したリクエスト」の場合と同様のやり方ですね。
「許可をしていない想定のOriginヘッダ値を付与したリクエスト」の場合との細かな違いとしてvariant playlisetとsegmentsについては、エラーメッセージがdisallowed origin
ではなく、origin required
になっていました。Originヘッダがない、という実態に即したエラーメッセージが返ってきたぐあいですね。そのほか、レスポンスにaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)が含まれていた点は同じでした。
multivariant playlist
% curl -i "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8" HTTP/2 403 content-type: application/json content-length: 159 date: Thu, 08 Feb 2024 08:03:36 GMT access-control-allow-origin: * x-amzn-trace-id: Root=1-65xxxxd8-0cxxxxxxxxxxxxxxxxxxxx25 x-amzn-trace-id: Root=1-65xxxxd8-0cxxxxxxxxxxxxxxxxxxxx25 x-cache: Error from cloudfront via: 1.1 02xxxxxxxxxxxxxxxxxxxxxxxxxxxxb4.cloudfront.net (CloudFront) x-amz-cf-pop: KIX50-P1 x-amz-cf-id: FAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx== [{"url":"/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8","error":"playback_auth_error","error_code":"playback_auth_error","type":"error"}]
variant playlist
いちどcurl -i -H "Origin: https://allowed-origin.example.net" <multivariant playlist>
で取得したプレイリスト内のvariant playlistを対象にリクエストを行います。
% curl -i "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列26]).m3u8" HTTP/1.1 403 Forbidden vary: Accept-Encodinga x-error-message: origin required date: Thu, 08 Feb 2024 08:04:30 GMT content-length: 0 access-control-allow-origin: *
segments
いちどcurl -i -H "Origin: https://allowed-origin.example.net" <variant playlist>
で取得したプレイリスト内のsegmentsに対してリクエストを行います。
% curl -i "https://video-edge-4fe7c8.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列133].ts" HTTP/1.1 403 Forbidden Access-Control-Allow-Origin: * Cache-Control: no-cache, no-store, private Content-Length: 15 origin required
検証結果のまとめ
(1) Playback Restriction Policyを適用していない状態、(2) Playback Restriction PolicyでAllowed Originを追加した状態(ただしStrict Origin Enforcementは無効)、(3) Playback Restriction PolicyでAllowed Originに加えてStrict Origin Enforcementを有効にした状態、それぞれでの、(a) 許可想定のOriginヘッダ値を付与したリクエスト、(b) 許可をしていない想定のOriginヘッダ値を付与したリクエスト、(c) Originヘッダなしのリクエスト、それぞれを3種のファイルに対して確認してきました。
ここでいちど検証結果について、Access-Control-Allow-Originヘッダの値の表としてまとめてみます。「ヘッダなし」についてはレスポンスにAccess-Control-Allow-Originヘッダ自体が含まれていないことを示します。
また「Allowed Originに加えてStrict Origin Enforcementを有効にした状態でのレスポンスヘッダの確認」の表については、Access-Control-Allow-Originヘッダの値のみではなく、HTTPステータスコードとエラーメッセージについて記載しています。
Playback Restriction Policyを適用していない状態でのレスポンスヘッダの確認
multivariant playlist |
variant playlist |
segments | |
---|---|---|---|
許可想定の Originヘッダ値を付与したリクエスト |
* | * | * |
許可をしていない想定の Originヘッダ値を付与したリクエスト |
* | * | * |
Originヘッダなしの リクエスト |
* | * | * |
Playback Restriction Policyを適用していない状態では、常にレスポンスヘッダにaccess-control-allow-origin: *
(Access-Control-Allow-Origin: *
)が含まれていいました。どのWebサイトでもストリーミングの再生は制限されていない、という状態です。またリクエストにOriginヘッダが含まれていなくても、Access-Control-Allow-Originヘッダがワイルドカード *
の値で返るためCORSエラーが発生して再生できない、といったことはありません。
Playback Restriction PolicyでAllowed Originを追加した状態でのレスポンスヘッダの確認
multivariant playlist |
variant playlist |
segments | |
---|---|---|---|
許可想定の Originヘッダ値を付与したリクエスト |
Originヘッダと同じ値(ホスト名) | * | * |
許可をしていない想定の Originヘッダ値を付与したリクエスト |
ヘッダなし | * | * |
Originヘッダなしの リクエスト |
ヘッダなし | * | * |
リクエスト時のOriginヘッダの値が、ストリーミング再生を許可したWebサイトのホスト名と異なる場合や、そもそもOriginヘッダがない場合、Playback Restriction PolicyでAllowed Originを追加している状態では、multivariant playlistのレスポンスにAccess-Control-Allow-Originヘッダを含まないという結果になりました。これで、ストリーミング再生を許可していないWebサイトでは、CORSエラーが発生してストリーミング再生が不可能となります。
ただし、multivariant playlist自体は取得が可能でプレイリスト内容が確認できます。そこから辿れるvariant playlistとsegmentsについては引き続きワイルドカード *
の値のAccess-Control-Allow-Originヘッダがレスポンスとして付与されます。Webサイト上の再生プレイヤーにvariant playlistを指定する、といった方法でAllowed Originに追加していないWebサイトからでも動画の再生、segmentsへのアクセスなどは理論上可能となります。今回の検証のようにcurlコマンドを利用する、またCORSのAccess-Control-Allow-Originヘッダを無視する動画プレイヤーを利用するなどとした場合に、ストリーミングの再生が可能になってしまうわけです。
Allowed Originに加えてStrict Origin Enforcementを有効にした状態でのレスポンスヘッダの確認
multivariant playlist |
variant playlist |
segments | |
---|---|---|---|
許可想定の Originヘッダ値を付与したリクエスト |
Originヘッダと同じ値(ホスト名) | * | * |
許可をしていない想定の Originヘッダ値を付与したリクエスト |
403 playback_auth_error * |
403 disallowed origin * |
403 disallowed origin * |
Originヘッダなしのリクエスト | 403 playback_auth_error * |
403 origin required * |
403 origin required * |
Allowed Originに加えてStrict Origin Enforcementを有効にした状態ではどうでしょうか。許可想定のOriginヘッダを付与したリクエストに対してはStrict Origin Enforcementが無効の状態と変わりません。Originヘッダの値が再生を許可していないWebサイトのホスト名やOriginヘッダがない場合は、一律で403
となりplaylistやsegmentsの内容が取得できません。Originヘッダの値を認証に使用し、正しい値を持たなければplaylist、segments自体を返さすストリーミング再生を一切行わせない、という挙動になっていますね。
まとめ
Amazon IVS Low-Latency StreamingのPlayback restriction policiesでStrict Origin Enforcementを有効にした際の挙動について、playlistやsegmentsにcurlコマンドでリクエストして確認してみました。
Playback restriction policiesでのみ再生制限をした場合(Strict Origin Enforcementが無効な場合)、レスポンスのAccess-Control-Allow-Originヘッダによって再生制限が行われ、playlistなどの情報自体は取得することができます。この情報を悪用させたくない、という場合はStrict Origin Enforcementを有効にしましょう。リクエスト時のOriginヘッダの値がAllowed Originで指定したものではない場合は、playlistやsegments自体が返らなくなります。その名称のとおり、より厳密にストリーミング再生の制限ができるわけですね。
指定したWebサイトでのみ再生を許可するといった場合にはこのPlayback restriction policies、厳密な制限の場合にはStrict Origin Enforcementを有効にして利用しましょう。またストリーミングを再生可能なユーザ自体を限定したい、といった場合にJSON Web Token (JWT)を使った再生制限、プライベートチャンネルと上手に使い分けていきましょう。